﻿namespace JumpJump.AI
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using JumpJump.Runtime;
    using JumpJump.Offline;
    
    /// <summary>
    /// this class use for helping computer move piece
    /// </summary>
    public class AIPrick
    {
        #region Fields

        /// <summary>
        /// use for store the current chessboard statue
        /// </summary>
        private Chessboard _currentChessBoard = null;

        /// <summary>
        /// user pieces attact value
        /// </summary>
        private int[] _userPiecesAttactScores = new int[10];

        /// <summary>
        /// user pieces defence value
        /// </summary>
        private int[] _userPiecesDefendScores = new int[10];

        /// <summary>
        /// AI pieces attact value
        /// </summary>
        private int[] _prickPiecesAttactScores = new int[10];

        /// <summary>
        /// AI pieces defence value
        /// </summary>
        private int[] _prickPiecesDefendScores = new int[10];

        /// <summary>
        /// current full board value
        /// </summary>
        private int _curentBoardScore = 0;

        /// <summary>
        /// all the valid movement for next
        /// </summary>
        private Dictionary<Movement, int> _nextBoardValueDic = new Dictionary<Movement, int>();

        /// <summary>
        /// chess manual list loaded from dat file
        /// </summary>
        private Dictionary<string, List<ManualAction>> _chessManualDic = new Dictionary<string, List<ManualAction>>();

        /// <summary>
        /// engine that will caculate out the final movement
        /// </summary>
        private AIMovementEngine _aiEngine;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the AIPrick class
        /// </summary>
        public AIPrick(Chessboard board)
        {
            this._currentChessBoard = board;
            _aiEngine = new AIMovementEngine(_currentChessBoard);
        }

        #endregion

        #region Propertites

        /// <summary>
        /// current chessboard
        /// </summary>
        public Chessboard CurrentChessBoard
        {
            get
            {
                return this._currentChessBoard;
            }

            set
            {
                this._currentChessBoard = value;
            }
        }

        /// <summary>
        /// AI engine
        /// </summary>
        public AIMovementEngine AIEngine
        {
            get
            {
                return this._aiEngine;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// get the next value accroding lots of computing
        /// </summary>
        /// <returns>the next movement</returns>
        public Movement MoveOnePiece()
        {
            Movement result = null;

            result = CanMoveAccordingManual();
            if (result != null)
            {
                return result;
            }

            result = _aiEngine.TryToMove();
            if (result != null)
            {
                return result;
            }

            else
            {
                return null;
            }
        }

        /// <summary>
        /// load chess manual from dat file
        /// </summary>
        /// <param name="path">dat file path</param>
        public void LoadChessManual(string path)
        {
            List<ChessManual> manualList = ChessManual.LoadFromDatFile(path);
            foreach (ChessManual cm in manualList)
            {
                _chessManualDic.Add(cm.StatueID, cm.ActionList);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// search the chessmanual, and find one matched the current chess board
        /// </summary>
        /// <returns>true false</returns>
        private Movement CanMoveAccordingManual()
        {
            Movement oneMove = null;
            string currentBoardID = ChessManual.GetUniqueStatueID(_currentChessBoard.Board);

            if (_chessManualDic.ContainsKey(currentBoardID))
            {
                ManualAction ma = _chessManualDic[currentBoardID][0];
                int pid = -1;
                int uid = -1;
                _currentChessBoard.GetPicecInfoFromCordinate(ma.FromX, ma.FromY, ref pid, ref uid);
                oneMove = ma.ToMoveMent(uid, pid);
                oneMove.Source = MovementSource.ChessManual;
            }

            return oneMove;
        }

        #endregion
    }
}
